// SPDX-License-Identifier: GPL-2.0

/*
 * Copyright (c) 2016-2018, LomboTech Co.Ltd. All rights reserved.
 * Author: lomboswer <lomboswer@lombotech.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/types.h>
#include <linux/io.h>

#include <mach/csp.h>
#include "csp_pdm.h"

#define PDM_ENABLE	1
#define PDM_DISABLE	0

#define PDM_START	1
#define PDM_STOP	0

#define PDM_RXDMA	(VA_PDM_RXDMA - VA_PDM)

/* enable pdm block */
void csp_pdm_enable(void *regs)
{
	reg_pdm_ctrl_t  pdm_ctrl;
	reg_pdm_t *reg_pdm = regs;

	/* enable pdm */
	pdm_ctrl.val = READREG32(&reg_pdm->ctrl);
	pdm_ctrl.bits.en = PDM_ENABLE;
	WRITEREG32(&reg_pdm->ctrl, pdm_ctrl.val);
}

/* disable pdm block */
void csp_pdm_disable(void *regs)
{
	reg_pdm_ctrl_t   pdm_ctrl;
	reg_pdm_t *reg_pdm = regs;

	/* disable pdm */
	pdm_ctrl.val = READREG32(&reg_pdm->ctrl);
	pdm_ctrl.bits.en = PDM_DISABLE;
	WRITEREG32(&reg_pdm->ctrl, pdm_ctrl.val);
}

/* enable hpf */
void csp_pdm_hpf_enable(void *regs)
{
	reg_pdm_ctrl_t   pdm_ctrl;
	reg_pdm_t *reg_pdm = regs;

	pdm_ctrl.val = READREG32(&reg_pdm->ctrl);
	pdm_ctrl.bits.hpf = PDM_ENABLE;
	WRITEREG32(&reg_pdm->ctrl, pdm_ctrl.val);
}

/* disable hpf */
void csp_pdm_hpf_disable(void *regs)
{
	reg_pdm_ctrl_t   pdm_ctrl;
	reg_pdm_t *reg_pdm = regs;

	pdm_ctrl.val = READREG32(&reg_pdm->ctrl);
	pdm_ctrl.bits.hpf = PDM_DISABLE;
	WRITEREG32(&reg_pdm->ctrl, pdm_ctrl.val);
}
/* open pdm rx channel */
void csp_pdm_rx_open(void *regs)
{
	reg_pdm_start_t pdm_start;
	reg_pdm_t *reg_pdm = regs;

	/* reset fifo */
	WRITEREG32(&reg_pdm->rxffr, 1);
	/* I2S Receive channel Enable */
	pdm_start.val = READREG32(&reg_pdm->start);
	pdm_start.bits.start = PDM_START;
	WRITEREG32(&reg_pdm->start, pdm_start.val);
}

/* close pdm rx channel */
void csp_pdm_rx_close(void *regs)
{
	reg_pdm_start_t pdm_start;
	reg_pdm_rxffr_t  pdm_rxffr;
	reg_pdm_t *reg_pdm = regs;

	/* write 1 reset rxfifo */
	pdm_rxffr.val = READREG32(&reg_pdm->rxffr);
	pdm_rxffr.bits.rxffr = 1;
	WRITEREG32(&reg_pdm->rxffr, pdm_rxffr.val);

	/* I2S Receive channel disable */
	pdm_start.val = READREG32(&reg_pdm->start);
	pdm_start.bits.start = PDM_STOP;
	WRITEREG32(&reg_pdm->start, pdm_start.val);
}

/* set sample bitwidth */
void csp_pdm_set_wlen(void *regs, u32 wlen)
{
	reg_pdm_rfcr_t pdm_rfcr;
	reg_pdm_t *reg_pdm = regs;

	pdm_rfcr.val = READREG32(&reg_pdm->rfcr);
	switch (wlen) {
	case 16:
		pdm_rfcr.bits.bw = PDM_RFCR_BW_1;
		break;
	case 32:
		pdm_rfcr.bits.bw = PDM_RFCR_BW_0;
		break;
	default:
		break;
	}
	WRITEREG32(&reg_pdm->rfcr, pdm_rfcr.val);
}

/* set pdm clk divider */
void csp_pdm_set_div(void *regs, u32 div)
{
	reg_pdm_ctrl_t pdm_ctrl;
	reg_pdm_t *reg_pdm = regs;

	pdm_ctrl.val = READREG32(&reg_pdm->ctrl);
	pdm_ctrl.bits.div = div;
	WRITEREG32(&reg_pdm->ctrl, pdm_ctrl.val);
}

/* set pdm osr */
void csp_pdm_set_osr(void *regs, u32 osr)
{
	reg_pdm_ctrl_t pdm_ctrl;
	reg_pdm_t *reg_pdm = regs;

	pdm_ctrl.val = READREG32(&reg_pdm->ctrl);
	switch (osr) {
	case 32:
		pdm_ctrl.bits.osr = PDM_CTRL_OSR_0;
		break;
	case 64:
		pdm_ctrl.bits.osr = PDM_CTRL_OSR_1;
		break;
	default:
		break;
	}
	WRITEREG32(&reg_pdm->ctrl, pdm_ctrl.val);
}

/* set pdm fs */
void csp_pdm_set_fs(void *regs, u32 fs)
{
	reg_pdm_ctrl_t cfg;
	reg_pdm_t *reg_pdm = regs;

	cfg.val = READREG32(&reg_pdm->ctrl);
	switch (fs) {
	case 8000:
		cfg.bits.fs = PDM_CTRL_FS_0;
		break;
	case 11025:
		cfg.bits.fs = PDM_CTRL_FS_1;
		break;
	case 16000:
		cfg.bits.fs = PDM_CTRL_FS_3;
		break;
	case 22050:
		cfg.bits.fs = PDM_CTRL_FS_4;
		break;
	case 24000:
		cfg.bits.fs = PDM_CTRL_FS_5;
		break;
	case 32000:
		cfg.bits.fs = PDM_CTRL_FS_6;
		break;
	case 44100:
		cfg.bits.fs = PDM_CTRL_FS_7;
		break;
	case 48000:
		cfg.bits.fs = PDM_CTRL_FS_8;
		break;
	case 88200:
		cfg.bits.fs = PDM_CTRL_FS_9;
		break;
	case 96000:
		cfg.bits.fs = PDM_CTRL_FS_A;
		break;
	case 192000:
		cfg.bits.fs = PDM_CTRL_FS_B;
		break;
	default:
		cfg.bits.fs = PDM_CTRL_FS_7;
		break;
	}

	WRITEREG32(&reg_pdm->ctrl, cfg.val);
}

/* set pdm channel */
void csp_pdm_set_channel(void *regs, u32 channel)
{
	reg_pdm_chan_t chan;
	reg_pdm_t *reg_pdm = (reg_pdm_t *)regs;

	chan.val = READREG32(&reg_pdm->chan);
	if (channel == 1)
		chan.bits.chanen = 1;
	else
		chan.bits.chanen = 0;
	WRITEREG32(&reg_pdm->chan, chan.val);
}

/* set data enable */
void csp_pdm_set_dat_enable(void *regs, u32 index)
{
	reg_pdm_chan_t chan;
	reg_pdm_t *reg_pdm = (reg_pdm_t *)regs;

	chan.val = READREG32(&reg_pdm->chan);

	chan.bits.daten = index;

	WRITEREG32(&reg_pdm->chan, chan.val);
}

/* SDIN dma addr */
u32 csp_pdm_dmaaddr_in(void)
{
	return PDM_RXDMA;
}

u32 csp_pdm_readl(void *regs)
{
	return 0;
}

u32 csp_pdm_readr(void *regs)
{
	return 0;
}

void csp_pdm_writel(void *regs, u32 val)
{
}

void csp_pdm_writer(void *regs, u32 val)
{
}


